﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using Projecturo.Model;
using System.Threading;
using Projecturo.ProjecturoClient.Connection;
using Projecturo.ProjecturoClient.Command;
using System.Windows.Input;
using Neits.PersistenceService.Providers;
using System.Text;
using System;

namespace Projecturo.ProjecturoClient.ViewModel.Dashboard
{
    public class DashboardViewModel : WorkspaceViewModel
    {
        private ObservableCollection<ViewModelBase> projects = new ObservableCollection<ViewModelBase>();
        private ObservableCollection<ViewModelBase> recentlyChangedTickets = new ObservableCollection<ViewModelBase>();
        private ObservableCollection<ViewModelBase> myOpenTickets = new ObservableCollection<ViewModelBase>();
        private ObservableCollection<ViewModelBase> newTickets = new ObservableCollection<ViewModelBase>();
        private ObservableCollection<ViewModelBase> reportedByMeTickets = new ObservableCollection<ViewModelBase>();
        private DelegateCommand newProjectCommand;
        private DelegateCommand newTicketCommand;
        private DelegateCommand userManagementCommand;
        private DelegateCommand userProfileCommand;
        private DelegateCommand searchTicketCommand;
        private string searchTicketId;

        public override string DisplayName
        {
            get
            {
                return "Dashboard";
            }
            protected set
            {
                base.DisplayName = value;
            }
        }

        private static User CurrentUser
        {
            get
            {
                return Thread.CurrentPrincipal as User;
            }
            set
            {
                Thread.CurrentPrincipal = value;
            }
        }

        public ICommand NewProjectCommand
        {
            get
            {
                if (newProjectCommand == null)
                {
                    newProjectCommand = new DelegateCommand(CreateNewProject);
                }
                return newProjectCommand;
            }
        }

        private void CreateNewProject()
        {
            ViewModelBase viewModel = ViewModelManager.Instance.CreateViewModel(typeof(Model.Project), this);
            AddToWorkspace(viewModel as WorkspaceViewModel, ViewModelReference, viewModel as WorkspaceViewModel);
        }

        public ICommand UserManagementCommand
        {
            get
            {
                if (userManagementCommand == null)
                {
                    userManagementCommand = new DelegateCommand(OpenUserManagement);
                }
                return userManagementCommand;
            }
        }

        private void OpenUserManagement()
        {
            ViewModelBase viewModel = ViewModelManager.Instance.CreateViewModel(typeof(Model.UserManagement), this);
            AddToWorkspace(viewModel as WorkspaceViewModel, ViewModelReference, viewModel as WorkspaceViewModel);
        }

        public ICommand UserProfileCommand
        {
            get
            {
                if (userProfileCommand == null)
                {
                    userProfileCommand = new DelegateCommand(OpenUserProfile);
                }
                return userProfileCommand;
            }
        }

        private void OpenUserProfile()
        {
            ViewModelBase viewModel = ViewModelManager.Instance.CreateViewModel(typeof(UserProfil), this);
            AddToWorkspace(viewModel as WorkspaceViewModel, ViewModelReference, viewModel as WorkspaceViewModel);
        }

        public ICommand NewTicketCommand
        {
            get
            {
                if (newTicketCommand == null)
                {
                    newTicketCommand = new DelegateCommand(CreateNewTicket);
                }
                return newTicketCommand;
            }
        }

        private void CreateNewTicket()
        {
            ViewModelBase viewModel = ViewModelManager.Instance.CreateViewModel(typeof(Ticket), this);
            AddToWorkspace(viewModel as WorkspaceViewModel, ViewModelReference, viewModel as WorkspaceViewModel);
        }

        public ICommand SearchTicketCommand
        {
            get
            {
                if (searchTicketCommand == null)
                    searchTicketCommand = new DelegateCommand(SearchTicket);
                return searchTicketCommand;
            }
        }

        private void SearchTicket()
        {
            long ticketId;
            if (long.TryParse(SearchTicketId, out ticketId))
            {
                var validProjectIds = new StringBuilder();
                foreach (Model.Project project in CurrentUser.Projects)
                {
                    validProjectIds.AppendFormat("{0},", project.Id);
                }
                if (validProjectIds.Length > 0)
                {
                    var filter =
                        new HqlFilter("from Ticket t where t.Id = " + ticketId + " and t.Project.Id in (" +
                                      validProjectIds.ToString().Substring(0, validProjectIds.Length - 1) + ")");

                    var foundTickets = Connector.Connectivity.Storage.GetList<Ticket>(filter);
                    if (foundTickets != null && foundTickets.Count > 0)
                    {
                        var viewModel = ViewModelManager.Instance.CreateViewModel(typeof (Ticket), this);
                        viewModel.SetModel(foundTickets[0]);
                        AddToWorkspace(viewModel as WorkspaceViewModel, ViewModelReference,
                                       viewModel as WorkspaceViewModel);
                    }
                }
            }
        }

        public string SearchTicketId
        {
            get { return searchTicketId; }
            set
            {
                if (searchTicketId == value)
                    return;
                searchTicketId = value;
                OnPropertyChanged("SearchTicketId");
            }
        }

        public ObservableCollection<ViewModelBase> Projects
        {
            get
            {
                return projects;
            }
        }

        public ObservableCollection<ViewModelBase> RecentlyChangedTickets
        {
            get
            {
                return recentlyChangedTickets;
            }
        }

        public ObservableCollection<ViewModelBase> MyOpenTickets
        {
            get
            {
                return myOpenTickets;
            }
        }

        public ObservableCollection<ViewModelBase> NewTickets
        {
            get
            {
                return newTickets;
            }
        }

        public ObservableCollection<ViewModelBase> ReportedByMeTickets
        {
            get
            {
                return reportedByMeTickets;
            }
        }

        protected override void OnViewModelCreated()
        {
            base.OnViewModelCreated();

            LoadProjects();
            LoadRecentlyChangedTickets();
            LoadMyTickets();
            LoadNewTickets();
            LoadReportedByMeTickets();
        }

        private void LoadProjects()
        {
            projects.Clear();
            if (CurrentUser != null && CurrentUser.Projects != null)
            {
                CurrentUser = Connector.Connectivity.Storage.Get<User>(CurrentUser.Id);
                foreach (Model.Project project in CurrentUser.Projects)
                {
                    ViewModelBase viewModelBase = ViewModelManager.Instance.CreateViewModel(typeof(Model.Project), this);
                    viewModelBase.SetModel(project);
                    projects.Add(viewModelBase);
                }
            }
        }

        private void LoadRecentlyChangedTickets()
        {
            RecentlyChangedTickets.Clear();
            var projectIds = GetAvailableProjectIds();
            if (String.IsNullOrEmpty(projectIds))
                return;
            if (CurrentUser != null)
            {
                HqlFilter filter = new HqlFilter("from Ticket t where t.AssignedTo = " + CurrentUser.Id +" and t.Project.Id in (" + projectIds + ") order by t.ChangeDate DESC");
                IList<Ticket> ticketsDb = Connector.Connectivity.Storage.GetList<Ticket>(filter);
                if (ticketsDb != null && ticketsDb.Count > 0)
                {
                    foreach (Ticket ticket in ticketsDb)
                    {
                        ViewModelBase viewModelBase = ViewModelManager.Instance.CreateViewModel(typeof(Ticket), this);
                        viewModelBase.SetModel(ticket);
                        RecentlyChangedTickets.Add(viewModelBase);
                    }
                }
            }
        }

        private void LoadMyTickets()
        {
            MyOpenTickets.Clear();
            var projectIds = GetAvailableProjectIds();
            if (String.IsNullOrEmpty(projectIds))
                return;
            if (CurrentUser != null)
            {
                var filter = new HqlFilter("from Ticket t where t.AssignedTo = " + CurrentUser.Id + " and t.State.Name != 'Closed' and t.Project.Id in (" + projectIds + ") order by t.ChangeDate DESC");
                IList<Ticket> ticketsDb = Connector.Connectivity.Storage.GetList<Ticket>(filter);
                if (ticketsDb != null && ticketsDb.Count > 0)
                {
                    foreach (Ticket ticket in ticketsDb)
                    {
                        ViewModelBase viewModelBase = ViewModelManager.Instance.CreateViewModel(typeof(Ticket), this);
                        viewModelBase.SetModel(ticket);
                        MyOpenTickets.Add(viewModelBase);
                    }
                }
            }
        }

        private string GetAvailableProjectIds()
        {
            var projectIds = new StringBuilder();
            foreach (var pro in CurrentUser.Projects)
            {
                projectIds.Append(pro.Id);
                projectIds.Append(",");
            }
            string returnString = projectIds.ToString();
            if (returnString.EndsWith(","))
                returnString = returnString.Substring(0, returnString.Length - 1);
            return returnString;
        }

        private void LoadNewTickets()
        {
            NewTickets.Clear();
            var projectIds = GetAvailableProjectIds();
            if (String.IsNullOrEmpty(projectIds))
                return;
            var filter = new HqlFilter("from Ticket t where t.State.Name = 'New' and t.Project.Id in (" + projectIds + ") order by t.ChangeDate ASC");
            IList<Ticket> ticketsDb = Connector.Connectivity.Storage.GetList<Ticket>(filter);
            if (ticketsDb != null && ticketsDb.Count > 0)
            {
                foreach (Ticket ticket in ticketsDb)
                {
                    ViewModelBase viewModelBase = ViewModelManager.Instance.CreateViewModel(typeof (Ticket), this);
                    viewModelBase.SetModel(ticket);
                    NewTickets.Add(viewModelBase);
                }
            }
        }

        private void LoadReportedByMeTickets()
        {
            ReportedByMeTickets.Clear();
            var projectIds = GetAvailableProjectIds();
            if (String.IsNullOrEmpty(projectIds))
                return;
            if (CurrentUser != null)
            {
                var filter = new HqlFilter("from Ticket t where t.CreatedBy.Id = " + CurrentUser.Id + " and t.Project.Id in (" + projectIds + ") order by t.ChangeDate DESC");
                IList<Ticket> ticketsDb = Connector.Connectivity.Storage.GetList<Ticket>(filter);
                if (ticketsDb != null && ticketsDb.Count > 0)
                {
                    foreach (Ticket ticket in ticketsDb)
                    {
                        ViewModelBase viewModelBase = ViewModelManager.Instance.CreateViewModel(typeof(Ticket), this);
                        viewModelBase.SetModel(ticket);
                        ReportedByMeTickets.Add(viewModelBase);
                    }
                }
            }
        }

        public override void Update()
        {
            LoadProjects();
            LoadMyTickets();
            LoadRecentlyChangedTickets();
            LoadNewTickets();
            LoadReportedByMeTickets();

            OnPropertyChanged("MyOpenTickets");
            OnPropertyChanged("RecentlyChangedTickets");

            base.Update();
        }
    }
}
